package com.cneport.transfer.handler.support;

import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

import com.cneport.transfer.ApplicationException;
import com.cneport.transfer.handler.MessageRouteHandler;
import com.cneport.transfer.message.Message;
import com.cneport.transfer.message.MessageImpl;
import com.cneport.transfer.router.MessageRouterImpl;
import com.cneport.transfer.router.model.RouterMessage;
import com.cneport.transfer.router.model.RouterType;
import com.sun.org.apache.xpath.internal.XPathAPI;


@Component
public class MessageRouteHandlerImpl implements MessageRouteHandler{
	private static final Log logger = LogFactory.getLog(MessageRouteHandler.class);
	java.util.concurrent.atomic.AtomicInteger successCount = new java.util.concurrent.atomic.AtomicInteger(0);
	java.util.concurrent.atomic.AtomicInteger failureCount = new java.util.concurrent.atomic.AtomicInteger(0);
	@Autowired
	private MessageRouterImpl messageRouter;
	
	private String errorChannelOut = "errorChannelOut";
	private String backupChannel = "remoteSendBackupChannel";
	private String routerErrorChannelOut = "routerErrorChannelOut";
	
	
	/**
	 * 1. parse messageHead
	 * 2. Sign/Verify process
	 * 3. router parse
	 * 4. compress/deCompress process
	 * 5. converter process
	 * 6. router. 
	 */

	public List<String> handle(String xmlData) {	
		List<String> results = new ArrayList<String>();
		String result = this.errorChannelOut;
		results.add(backupChannel);
		
		try{
			backupMessageBefore(xmlData);
			
			Message<String> message= parseMessage(xmlData);
			message = compressProcess(message,xmlData);
			message = signProcess(message,xmlData);
			message = converterProcess(message,xmlData);
			backupMessageAfter(xmlData);
			RouterMessage routerMessage = messageRouter.route(message);
			result = findTargetOutputChannel(routerMessage,message);
			
		}catch(ApplicationException ex){
			backupMessageError(xmlData);
			results.clear();
			results.add(this.routerErrorChannelOut);
		}catch(Exception e){
			backupMessageError(xmlData);
			results.clear();
			results.add(this.errorChannelOut);
		}
		results.add(result);
		return results;
	}
	
	


	private String findTargetOutputChannel(RouterMessage routerMessage,Message<String> message){
		String targetChannel = "";
		 
		if(routerMessage.getRouterType().equals(RouterType.user)){
			targetChannel= message.getReceiverId().split("@")[0]+"ftpChannelOut";
		}else if(routerMessage.getRouterType().equals(RouterType.node)){
			targetChannel= routerMessage.getNode().getNodeId()+"wmqChannelOut";
		}else {
			targetChannel= message.getSenderId().split("@")[0]+"ftpChannelOut";
		}
		logger.info("###############MessageRouteHandlerImpl.findTargetOutputChannel : "+targetChannel);
		
		return targetChannel;
	}
	
	
	private Message<String> parseMessage(String message) throws Exception{
		Message<String> messageImpl = new MessageImpl();		
		StringReader sr = new StringReader(message);
		InputSource is = new InputSource(sr);
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		factory.setNamespaceAware(true);
		DocumentBuilder builder;
		builder = factory.newDocumentBuilder();
		Document document = builder.parse(is);
		String root = document.getFirstChild().getNodeName();
		if ("dxp:DxpMsgCl".equals(root)) {
			org.w3c.dom.Node node = XPathAPI.selectSingleNode(document,"//dxp:DxpMsgCl/dxp:ClNo");
			String senderId = XPathAPI.selectSingleNode(node, "dxp:SendId").getTextContent();
			messageImpl.setSenderId(senderId);
			
			org.w3c.dom.Node receiver = XPathAPI.selectSingleNode(node, "dxp:Receivers");
			NodeList receiverIds = XPathAPI.selectNodeList(receiver, "dxp:Id");
			String receiverId = receiverIds.item(0).getTextContent();
			messageImpl.setReceiverId(receiverId);
			
			messageImpl.setMessageData(message);
		}
		return messageImpl;
	}



	private Message<String> converterProcess(Message<String> message, String xmlData) {
		return message;
	}


	private Message<String> signProcess(Message<String> message, String xmlData) {
		return message;
	}

	private Message<String> compressProcess(Message<String> message, String xmlData) {
		return message;
	}

	private void backupMessageError(String message) {
		logger.error("process error:\n");
		logger.error(message);
		
	}

	private void backupMessageAfter(String message) {
		logger.info("process after:\n");
		logger.info(message);
		
	}

	private void backupMessageBefore(String message) {
		logger.info("process before:\n");
		logger.info(message);
		
	}

}
